object HigherOrderFunctionsDemo extends App {
  case class Student(
                      id: String,
                      name: String,
                      className: String,
                      gender: String,
                      grade: Int,
                      age: Int,
                      scores: Map[String, Double]
                    )
  val students = List(
    Student("S2826001", "张三", "计科1班", "男", 1, 18, Map("数学" -> 85.0, "语文" -> 90.0)),
    Student("S2826002", "李四", "计科1班", "男", 1, 19, Map("数学" -> 92.0, "语文" -> 82.0)),
    Student("S2826003", "王五", "计科2班", "女", 1, 18, Map("数学" -> 76.0, "语文" -> 86.0)),
    Student("S2826004", "赵六", "软工1班", "男", 1, 19, Map("数学" -> 68.0, "语文" -> 72.0)),
    Student("S2826005", "钱七", "计科2班", "女", 1, 18, Map("数学" -> 90.0, "语文" -> 88.0)),
    Student("S2826001", "孙八", "计科1班", "男", 2, 20, Map("数学" -> 88.0, "语文" -> 85.0))
  )

  def groupAndAggregate[T, K, V](
                                  data: List[T],
                                  groupByFunc: T => K,
                                  aggregateFunc: List[T] => V
                                ): Map[K, V] = {
    data.groupBy(groupByFunc).map { case (key, groupData) =>
      (key, aggregateFunc(groupData))
    }
  }
  val groupByClass = (s: Student) => s.className
  val groupByGender = (s: Student) => s.gender
  val groupByGrade = (s: Student) => s.grade
  val countStudents = (group: List[Student]) => group.size
  val averageAge = (group: List[Student]) => group.map(_.age).sum.toDouble / group.size
  val averageMathScore = (group: List[Student]) => {
    val total = group.flatMap(_.scores.get("数学")).sum
    total / group.size
  }
  println("=== 按班级统计学生数量 ===")
  val classCount = groupAndAggregate(students, groupByClass, countStudents)
  classCount.foreach { case (className, count) =>
    println(s"$className: $count 人")
  }

  println("\n=== 按性别统计平均年龄 ===")
  val genderAgeAvg = groupAndAggregate(students, groupByGender, averageAge)
  genderAgeAvg.foreach { case (gender, avg) =>
    println(s"$gender: $avg%.1f 岁")
  }

  println("\n=== 按班级统计数学平均分 ===")
  val classMathAvg = groupAndAggregate(students, groupByClass, averageMathScore)
  classMathAvg.foreach { case (className, avg) =>
    println(s"$className: $avg%.1f 分")
  }
  def createSubjectAvgFunc(subject: String): List[Student] => Double = {
    (group: List[Student]) => {
      val total = group.flatMap(_.scores.get(subject)).sum
      if (group.isEmpty) 0.0 else total / group.size
    }
  }
  val chineseAvgFunc = createSubjectAvgFunc("语文")

  println("\n=== 按年级统计语文平均分 ===")
  val gradeChineseAvg = groupAndAggregate(students, groupByGrade, chineseAvgFunc)
  gradeChineseAvg.foreach { case (grade, avg) =>
    println(s"$grade 年级: $avg%.1f 分")
  }
}